import csv
import jieba
from wordcloud import WordCloud
from functools import reduce

def clear_str(s):
    """
    This is used to clear the chinese lyric string.
    
    Args:
    - s: the input string.
    
    Returns:
    - r: the target string.
    """
    r = s
    
    r = r.replace('本作品经过原词曲版权方授权','')
    r = r.replace('本歌曲来自〖网易音乐人〗亿现金激励，千亿流量扶持！','')
    r = r.replace('本歌曲来自〖网易猎音计划〗','')
    r = r.replace('本歌曲来自〖网易飓风计划〗','')
    r = r.replace('本歌曲来自〖网易音乐人〗亿现金激励，千亿流量扶持！','')
    r = r.replace('亿现金激励，千亿流量扶持！', '')
    r = r.replace('就到老网易云音乐「创造者计划」出品','')
    r = r.replace('\u200b','')
    r = r.replace('\u3000','')
    r = r.replace('\xa0','')
    r = r.replace('\n','')
    r = r.replace('\r','')
    r = r.replace('\t','')
    r = r.replace(' ','')
    r = r.replace('﹉','')
    r = r.replace('，','')
    r = r.replace('。','')
    r = r.replace('“','')
    r = r.replace('”','')
    r = r.replace('！','')
    r = r.replace('？','')
    r = r.replace('?','')
    r = r.replace(';','')
    r = r.replace('~','')
    r = r.replace('/','')
    r = r.replace('／','')
    r = r.replace('…','')
    r = r.replace('·','')
    r = r.replace('「','')
    r = r.replace('」','')
    r = r.replace('…','')
    r = r.replace('～','')
    r = r.replace('﹝','')
    r = r.replace('﹞','')
    r = r.replace('；','')
    r = r.replace('‘','')
    r = r.replace('’','')
    r = r.replace('|','')
    r = r.replace('@','')
    r = r.replace('❤','')
    r = r.replace('㙓','')
    r = r.replace('머','')
    r = r.replace('✦','')
    r = r.replace('☪','')
    r = r.replace('✿','')
    r = r.replace('❀','')
    r = r.replace('⋯','')
    r = r.replace('\u2028','')
    r = r.replace('\ufeff','')
    r = r.replace('・','')
    r = r.replace('不','不')
    r = r.replace('了','了')
    r = r.replace('♡','')
    r = r.replace('⼀','')
    r = r.replace('⼭','山')
    r = r.replace('⾛','走')
    r = r.replace('⽕','火')
    r = r.replace('⼼','心')
    r = r.replace('⾃','自')
    r = r.replace('⼿','手')
    r = r.replace('⽇','日')
    r = r.replace('⽆','无')
    r = r.replace('⾳','音')
    r = r.replace('⼤','大')
    r = r.replace('⽓','气')
    r = r.replace('⽌','止')
    r = r.replace('⾥','里')
    r = r.replace('⽔','水')
    r = r.replace('⻜','飞')
    r = r.replace('⻥','鱼')
    r = r.replace('⻛','风')
    r = r.replace('⼊','入')
    r = r.replace('「','')
    r = r.replace('」','')
    r = r.replace('｢','')
    r = r.replace('｣','')
    r = r.replace('⻅','见')
    r = r.replace('⻦','鸟')
    r = r.replace('⻘','青')
    r = r.replace('⻉','贝')
    r = r.replace('⻓','长')
    r = r.replace('￼','')
    r = r.replace('\u200c','')
    r = r.replace('₍','')
    r = r.replace('ᐢ','')
    r = r.replace('⾚','赤')
    r = r.replace('₎','')
    r = r.replace('⾬','雨')
    r = r.replace('⽐','比')
    r = r.replace('ل','')
    r = r.replace('⼒', '力')
    r = r.replace('⻆','角')
    r = r.replace('⽣','生')
    r = r.replace('⾼','高')
    r = r.replace('⾎','血')
    r = r.replace('⽅','方')
    r = r.replace('⿎','鼓')
    r = r.replace('⽤','用')
    r = r.replace('⾏','行')
    r = r.replace('⼩','小')
    r = r.replace('⽹','网')
    r = r.replace('⾏','行')
    r = r.replace('⽅','方')
    r = r.replace('⾄','至')
    r = r.replace('⾯','面')
    r = r.replace('⽉','月')
    r = r.replace('⽛','牙')
    r = r.replace('⾹','香')
    r = r.replace('⽩','白')
    r = r.replace('⽩','白')
    r = r.replace('⼝','口')
    r = r.replace('⻨','麦')
    r = r.replace('⻁','虎')
    r = r.replace('⼈','人')
    r = r.replace('⼰','己')
    r = r.replace('♩','')
    r = r.replace('♬','')
    r = r.replace('','')
    r = r.replace('','')
    r = r.replace('','')
    r = r.replace('','')
    
    return r


def get_corpus(data, labels=[0,1,2,3]):
    """
   This function gets the corpus of corresponding type of lyric.
   
   Args:
   - data: :numpy.array: (n, 2) the first is the lyric and the second is corresponding label.
   - labels: :list: the label of corpus that we want.
   
   Returns:
   - corpus: dict of corresponding corpus. 
   - total_corpus: :list: total lyrics.
    """
    total_corpus = data[:,0]
    corpus = {}
    for label in labels:
        lb = data[:,1].astype('int')
        corpus[label] = data[lb == label,0]
    return corpus, total_corpus


def get_vocabulary(corpus):
    """
   This function gets the vocabulary of the corpus.
   
   Args:
   - corpus: :list: total corpus, containing all possible chars appear in our task.
   
   Returns:
   - vocabulary: :list: vocabulary over the corpus.
   - char_to_indices: :dict: a dictionary of char to index.
    """
    corpus = reduce(lambda x, y: x+y, corpus)
    vocabulary = list(set(corpus))
    char_to_indices = dict((char,i) for i, char in enumerate(vocabulary))
    return vocabulary, char_to_indices


def get_dict_largest(d, n=1):
    """
   Get the keys with most largest n values.
   
   Args:
   - d: :dict: the dict.
   - n: :math: the most largest number
   
   Returns:
   - keys: :list: list of corresponding keys
    """
    n = min(n, len(d))
    temp = sorted(d.items(), key=lambda d: d[1], reverse=True) # dict after sort
    keys = [temp[i][0] for i in range(n)]
    return keys


def get_word_frequency(corpus):
    """
   Compute the frequency of words in corpus. And we use jieba to split.
   
   Args:
   - corpus: :numpy.ndarray: (n,) every item is a string representing a lyric.
   
   Returns:
   - freq: :dict: record the frequency of each word appears in the corpus.
    """
    freq = {}
    for i in range(len(corpus)):
        for word in jieba.cut(corpus[i]):
            if word in freq:
                freq[word] += 1
            else:
                freq[word] = 1
    return freq


def get_wordcloud(corpus, n=50, name=None):
    """
   This function generates wordcloud for the corpus.
   
   Args:
   - corpus: :numpy.ndarray: (n,) every item is a string representing a lyric.
   - n: :math: we choose the most frequent n word to generate the wordcloud.
   - name: :string: name for saving.
    
    """
    assert n > 0, 'the number n should be non-negative.'
    assert name != None, 'You should define name for saving.'
    freq = get_word_frequency(corpus)
    keys = get_dict_largest(freq, n)
    final = ''
    for word in keys:
        final = final + word + ' '
    w = WordCloud(font_path=r'C:\Windows\Fonts\simkai.ttf',
                    width=2000, height=1000, background_color="white")
    
    w.generate(final)
    w.to_file('pywcloud_' + name + '.png')
    
    
def str_to_idx(lyric, char_to_indices):
    """
    [TODO](zbw): to implement char-to-idx
   This function transforms the charaters into indices of the vocabulary. 
   
   Args:
   - lyric: :list: a list of lyric.
   - char_to_indices: :dict: vocabulary over our task corpus.
   
   Returns:
   - indices: :list: the corresponding indices of the input lyric.
    """
    raise NotImplementedError
    indices = []
    return indices
    
    
def idx_to_char(indices, vocabulary):
    """
    [TODO](zbw): to implement idx-to-char
   This function transforms the indices into corresponding characters.
   
   Args:
   - indices: :list: the indices of lyric.
   - vocabulary: :list: vocabulary over the corpus.
   
   Returns:
   - lyric: :list: list of lyric.
    """    
    raise NotImplementedError
    
    